import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

/**
 * AdjacencyList class, which takes all the vertex
 * @author ldong
 *
 */
public class AdjacencyList
{
	private String filePath;
	private HashMap<String, Vertex> adjacentStringVertextable;
	

	/**
	 * constructor
	 */
	public AdjacencyList()
	{
		adjacentStringVertextable = new HashMap<String, Vertex>();
	}
	
	
	/**
	 * Ask for the file name 
	 * @throws IOException
	 */
	public void enterInput() throws IOException
	{
        System.out.print("Please type your file name correctly -> ");
        getFileName();
        readFile();
	}
	
	/**
	 * Get the file name
	 */
	private void getFileName()
	{
        Scanner scan = new Scanner(System.in);
        filePath = scan.nextLine();
	}
    
	/**
	 * read the file from the filepath
	 * @throws IOException
	 */
    private void readFile() throws IOException {

            Scanner scanFile = null;
            System.out.println(filePath +" is opened");
            try {
               scanFile = new Scanner(new BufferedReader(new FileReader(filePath)));
               // Print out the outputs
               while (scanFile.hasNext())
               {
	            	String a = scanFile.next();
	            	String b = scanFile.next();
	            	int c = Integer.parseInt(scanFile.next());
        	/*                                                 */                	
        	/* Now should call build a new Vertex with weights */
        	/*                                                 */
        	         addVertex2List(a,b,c);
                }
                
            } 
            catch(IOException io){
              System.out.println("File Not Found, Please do it correctly!!");
            } finally {
                	scanFile.close();
            }
        }
    
    /**
     * return the Vertex of the given name
     * @param name
     * @return
     */
    public Vertex createVertex(String name)
    {
       //  if this vertex doesnt exist
       if(name != null && !adjacentStringVertextable.containsKey(name))
       {
    	   Vertex v = new Vertex(name);
    	   adjacentStringVertextable.put(name, v);
    	   return v;
       }
       else
	      return adjacentStringVertextable.get(name);
    }
    
    /**
     * add v and w to each other
     * @param v
     * @param w
     * @param weight
     */
    public void createWeight(Vertex v, Vertex w, int weight)
    {
    	v.addAdjacentWeight(w, weight);
    	w.addAdjacentWeight(v, weight);
    }
    
    /**
     * add a vertex to the list
     * @param a
     * @param b
     * @param weight
     * @return
     */
    public boolean addVertex2List(String a, String b, int weight)
    {
    	
    	Vertex v = createVertex(a);
    	Vertex w = createVertex(b);
        if(v !=null && w != null)
    	{ 
        	createWeight(v,w,weight);
        	return true;
        }
    	else
    		 return false;
    	
    }
    
    /**
     * Reset the boolean flags to the true/ false which passed in as parameter
     */
    public void resetFlag(boolean mark)
    {
    	Set<Map.Entry<String, Vertex>> entrySet = adjacentStringVertextable.entrySet();
        
        for(Map.Entry<String, Vertex> map : entrySet)
        {
        	map.getValue().setMark(mark);
        }
    }
    /**
     * Overriding toString method
     */
     public String toString()
     {
    	String temp = "";

    	Set<Map.Entry<String, Vertex>> entrySet = adjacentStringVertextable.entrySet();
        
        for(Map.Entry<String, Vertex> map : entrySet)
        {	  
  	      temp +=   map.getValue()+ "\n";
        }  	   
     	
    	 return temp;
     }
    
     /**
      * Return a vertex given the name of that vertex
      * @param name
      * @return
      */
    public Vertex getSpecificVertex(String name)
    {
    	if(adjacentStringVertextable.containsKey(name))
    		return adjacentStringVertextable.get(name);
    	else 
    		return null;
    }
    /**
     * getter
     * @return
     */
 	public HashMap<String, Vertex> getAdjacentStringVertextable() {
		return adjacentStringVertextable;
	}

 	/**
 	 * setter
 	 * @param adjacentStringVertextable
 	 */
	public void setAdjacentStringVertextable(
			HashMap<String, Vertex> adjacentStringVertextable) {
		this.adjacentStringVertextable = adjacentStringVertextable;
	}

	/**
	 * Return a set of vertices
	 * @return
	 */
    public Set<Vertex> returnVertex()
    {
    	Set<Vertex> tree = new TreeSet<Vertex>(); 
        Set<Entry<String, Vertex>> entrySet 
                        = adjacentStringVertextable.entrySet();
        for(Map.Entry<String, Vertex> map : entrySet )
        	tree.add(map.getValue());

        return tree;

    }
    
}
